
#encoding: latin-1

from Variables import *

class Plateau:
    """Gère le plateau de jeu et contient toutes les méthodes pour tester les déplacements, calcul de score, etc."""
        
    def __init__(self, plateau):
        """ Constructeur. Peut jouer le rôle de constructeur par défaut, ou de constructeur par copie.  """
        
        if isinstance(plateau, list):
            self.grille = plateau[:]
            self.varCasesVides = CASES_VIDES_INITIAL[:]
        elif isinstance(plateau, Plateau):
            self.grille = plateau.grille[:]
            self.varCasesVides = plateau.varCasesVides[:]
    
    def coupAcceptable(self, i, joueur):
        """ Teste si le coup à la case numéro i par le joueur est acceptable. Si on renvoie True, on peut au moins retourner un pion adverse avec ce coup. On vérifie au préalable que la case est vide. """
        
        if self.grille[i] == 0:     # si la case est vide on effectue les tests.
            adversaire = 3 - joueur # Si joueur = 1, alors adversaire = 2. Si joueur = 2, alors adversaire = 1.
            
            # Dans Othello on peut manger un pion dans toutes les directions possibles (il y en a 8), donc on effectue les tests dans toutes ces directions.
            
            k = i-1 # à gauche
            if self.grille[k] == adversaire:
                k -= 1
                while self.grille[k] == adversaire: 
                    k -= 1
                if self.grille[k] == joueur: 
                    return True

            k = i+1 # à droite
            if self.grille[k] == adversaire:
                k += 1
                while self.grille[k] == adversaire: 
                    k += 1
                if self.grille[k] == joueur: 
                    return True
    
            k = i-10  # en haut
            if self.grille[k] == adversaire:
                k -= 10
                while self.grille[k] == adversaire: 
                    k -= 10
                if self.grille[k] == joueur: 
                    return True
            
            k = i-11 # en haut à gauche
            if self.grille[k] == adversaire:
                k -= 11
                while self.grille[k] == adversaire: 
                    k -= 11
                if self.grille[k] == joueur: 
                    return True                
    
            k = i-9 # en haut à droite
            if self.grille[k] == adversaire:
                k -= 9
                while self.grille[k] == adversaire: 
                    k -= 9
                if self.grille[k] == joueur: 
                    return True
                
            k = i+10 # en bas 
            if self.grille[k] == adversaire:
                k += 10
                while self.grille[k] == adversaire: 
                    k += 10
                if self.grille[k] == joueur: 
                    return True
            
            k = i+9 # en bas à gauche
            if self.grille[k] == adversaire:
                k += 9
                while self.grille[k] == adversaire: 
                    k += 9
                if self.grille[k] == joueur: 
                    return True
        
            k = i+11 # en bas à droite
            if self.grille[k] == adversaire:
                k += 11
                while self.grille[k] == adversaire: 
                    k += 11
                if self.grille[k] == joueur: 
                    return True                
                                           
        return False
                        
    def peutJouer(self, joueur):
        """ Teste si le joueur peut jouer ou non. Si on renvoie False alors le joueur ne peut pas jouer. """
        
        for i in self.varCasesVides:           # Pour chaque élément de cases_vides
            if self.coupAcceptable(i, joueur): # On teste si le coup est acceptable 
                return True
        return False
    
    def coupsPossibles(self, joueur):
        """ Renvoie tous les coups possibles pour le joueur. """
        
        coups = []
        for i in self.varCasesVides :
            if self.coupAcceptable(i, joueur) :
                coups.append(i)
        return coups

    def coup(self, i, joueur):
        """ Effectue, pour le joueur, le coup à la case numéro i. """
        
        adversaire = 3 - joueur
        self.grille[i] = joueur # On joue le coup
        self.varCasesVides.remove(i)
        
        k = i-1
        while self.grille[k] == adversaire: 
            k -= 1
        if self.grille[k] == joueur:
            k += 1
            while self.grille[k] == adversaire:
                self.grille[k] = joueur
                k += 1
                
        k = i+1
        while self.grille[k] == adversaire: 
            k += 1
        if self.grille[k] == joueur:
            k -= 1
            while self.grille[k] == adversaire:
                self.grille[k] = joueur
                k -= 1
                
        k = i-10
        while self.grille[k] == adversaire:
            k -= 10
        if self.grille[k] == joueur:
            k += 10
            while self.grille[k] == adversaire:
                self.grille[k] = joueur
                k += 10
                
        k = i+10
        while self.grille[k] == adversaire:
            k += 10
        if self.grille[k] == joueur:
            k -= 10
            while self.grille[k] == adversaire:
                self.grille[k] = joueur
                k -= 10
                
        k = i-11
        while self.grille[k] == adversaire: 
            k -= 11
        if self.grille[k] == joueur:
            k += 11
            while self.grille[k] == adversaire:
                self.grille[k] = joueur
                k += 11
                
        k = i+11
        while self.grille[k] == adversaire:
            k += 11
        if self.grille[k] == joueur:
            k -= 11
            while self.grille[k] == adversaire:
                self.grille[k] = joueur
                k -= 11
                
        k = i-9
        while self.grille[k] == adversaire:
            k -= 9
        if self.grille[k] == joueur:
            k += 9
            while self.grille[k] == adversaire:
                self.grille[k] = joueur
                k += 9
                
        k = i+9
        while self.grille[k] == adversaire:
            k += 9
        if self.grille[k] == joueur:
            k -= 9
            while self.grille[k] == adversaire:
                self.grille[k] = joueur
                k -= 9
            
    def score(self):
        """ Retourne le score de la partie (en cours ou non). Un pion équivaut à un point. """
        
        return self.grille.count(1), self.grille.count(2)
    
    def nbCoupsPossibles(self):
        """ Renvoie le nombre de coups possibles pour chaque joueur. """
               
        joueur1 = 0
        joueur2 = 0
        for i in self.varCasesVides:
            if self.grille[i] == 0:
                joueur1 += self.coupAcceptable(i, 1)
                joueur2 += self.coupAcceptable(i, 2)
        return joueur1, joueur2
    
    def nbPionsIntouchables(self):
        """ Renvoie, pour chaque joueur, le nombre de pions qui ne pourront pas être mangés par l'autre joueur. """
        
        joueur1 = 0
        joueur2 = 0
        
        for i in PLACER_PION_INITIAL:
            if self.grille[i] == 1:
                joueur1 += self.pionIntouchable(i)
            elif self.grille[i] == 2:
                joueur2 += self.pionIntouchable(i)
        return joueur1, joueur2
    
    def pionIntouchable(self, i):
        """ Teste si le pion à la case numéro i du plateau est intouchable ou pas. """
        
        joueur = self.grille[i]
        adversaire = 3 - joueur
        
        k = i - 10
        while self.grille[k] == joueur:
            k -= 10
        if self.grille[k] == 0 or self.grille[k] == adversaire:
            temp = self.grille[k]
            k = i + 10
            while self.grille[k] == joueur:
                k += 10
            if self.grille[k] == 0 or (self.grille[k] == adversaire and temp == 0):
                return False
                
        k = i - 1
        while self.grille[k] == joueur:
            k -= 1
        if self.grille[k] == 0 or self.grille[k] == adversaire:
            temp = self.grille[k]
            k = i + 1
            while self.grille[k] == joueur:
                k += 1
            if self.grille[k] == 0 or (self.grille[k] == adversaire and temp == 0):
                return False
                
        k = i - 11
        while self.grille[k] == joueur:
            k -= 11
        if self.grille[k] == 0 or self.grille[k] == adversaire:
            temp = self.grille[k]
            k = i + 11
            while self.grille[k] == joueur:
                k += 11
            if self.grille[k] == 0 or (self.grille[k] == adversaire and temp == 0):
                return False
                
        k = i - 9
        while self.grille[k] == joueur:
            k -= 9
        if self.grille[k] == 0 or self.grille[k] == adversaire:
            temp = self.grille[k]
            k = i + 9
            while self.grille[k] == joueur:
                k += 9
            if self.grille[k] == 0 or (self.grille[k] == adversaire and temp == 0):
                return False
                
        return True
        
    def scorePosition(self):
        """ Sert à la prise de décision de l'ordinateur. Cette fonction calcule le score d'une position potentielle, en fonction de différents parametres, à un moment du jeu. """
        
        ScoreNoir, ScoreBlanc = self.score()
        
        if ScoreNoir == 0 or ScoreBlanc == 0:
            return (ScoreBlanc == 0) * INFINITY, (ScoreNoir == 0) * INFINITY
            
        ScoreNoir *= -1
        ScoreBlanc *= -1
        joueur1, joueur2 = self.nbCoupsPossibles()
        ScoreNoir += 2 * joueur1
        ScoreBlanc += 2 * joueur2
        
        for i in PLACER_PION_INITIAL:
            if self.grille[i] == 1:
                ScoreNoir += VAL_CASE[i]
            elif self.grille[i] == 2:
                ScoreBlanc += VAL_CASE[i]
                
        intouchable1, intouchable2 = self.nbPionsIntouchables()
        ScoreNoir += 3 * intouchable1
        ScoreBlanc += 3 * intouchable1
        
        return ScoreNoir, ScoreBlanc
        
        
        
        
        
        
        
    
    